Optional Collections.f

Requires Dorothy.f

0 value powers
: power/2 ( n -- n )
   0 to powers
   1 begin over over > while 1 +to powers 2* repeat nip ;

: power/2?   dup power/2 = ;

: >powers/2 ( n -- n )
   power/2 drop powers ;

\ -- Arrays --

: any.[]
   state @ if
      type> sizeof
      dup power/2? if
         postpone swap >powers/2 postpone literal postpone lshift postpone +
      else
         postpone swap postpone literal postpone * postpone +
      then
   else
      swap type> typedef.size @ * +
   then ; immediate

: any.next
   type> sizeof
   state @ if
      postpone literal postpone +
   else + then ; immediate

: ?literal  state @ if postpone literal then ;

: any.length
   target> target.count @ ?literal ; immediate

\ Address or address-fetching code should already have been compiled; we just calculate the total size here.
: any.count  ( array -- array bytes )
   type> sizeof target> target.count @ * ?literal ; immediate

\ Typedef word
: any.*
   type> sizeof ?literal " * " -evaluate ; immediate


\ -- Double linked lists --

\ DO NOT MODIFY
type: node
   node.pointer prev
   node.pointer next
   node.pointer first
   node.pointer last
   node.pointer parent
end-type

: node.[]
   first swap 0 ?do next loop ;

method: node.remove
   parent if
      prev if  next to prev.next
      else     next to parent.first   then
      next if  prev to next.prev
      else     prev to parent.last    then
   0 to parent
   then ;

0 node.ref dest
0 node.ref src

: node.link  ( src dest -- )
   over remove  to dest to src
   dest to src.prev
   dest.next to src.next
   dest.next if
      src to dest.next.prev
   else
      dest.parent if
         src to dest.parent.last
      then
   then
   src to dest.next
   dest.parent to src.parent ;

: node.insert  ( src dest -- )
   over remove  to dest to src
   dest.prev to src.prev
   dest to src.next
   dest.prev if
      src to dest.prev.next
   else
      dest.parent if
         src to dest.parent.first
      then
   then
   src to dest.prev
   dest.parent to src.parent ;

: node.add  ( src dest -- )
   to dest to src
   dest.last ?dup if
      src swap link
   else
      src dup to dest.first
              to dest.last
      0 dup to src.next
            to src.prev
      dest to src.parent
   then ;


:[] node.each:[
   >q first begin
   dup while
      dup q@ execute
      next
   repeat
   q> drop
   drop ;


\ -- Static lists --

Type: static-list
   any.pointer last
end-type


\\
\ Test

node.make a
node.make b
node.make c

